﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;

namespace WorkStation.Frameworks.Core.Data.Linq
{
    /// <summary>
    /// * 表达式组合工具类
    /// </summary>
    public class ComposeExpressionTool : ExpressionVisitor
    {
        private List<ParameterExpression> _parameters;

        private LambdaExpression _left;
        private LambdaExpression _right;
        private Func<Expression, Expression, Expression> _operatorFunction;

        /// <summary>
        /// * 构造函数
        /// </summary>
        /// <param name="left">左表达式</param>
        /// <param name="right">右表达式</param>
        /// <param name="operatorFunction">二元运算符</param>
        public ComposeExpressionTool(LambdaExpression left, LambdaExpression right, Func<Expression, Expression, Expression> operatorFunction)
        {
            this._left = left;
            this._right = right;

            this._operatorFunction = operatorFunction;

            this._parameters = new List<ParameterExpression>();

            this._parameters.AddRange(this._left.Parameters.ToList());
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            foreach (ParameterExpression parameter in this._parameters)
            {
                if (object.ReferenceEquals(parameter, node))
                {
                    return parameter;
                }
            }

            return base.VisitParameter(node);
        }

        /// <summary>
        /// * 组合表达式
        /// </summary>
        /// <returns></returns>
        public LambdaExpression ComposeExpression()
        {
            this._right = this.Visit(this._right) as LambdaExpression;

            return LambdaExpression.Lambda(this._operatorFunction(this._left.Body, this._right.Body), this._left.Parameters);
        }
    }
}
